package de.preamp.clients.java.net;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.ProgressMonitorInputStream;

import org.json.JSONException;

import de.preamp.clients.java.data.Album;
import de.preamp.clients.java.data.Artist;
import de.preamp.clients.java.data.Track;
import de.preamp.clients.java.utils.AbstractPreferences;

/**
 * A class managing the download of media files to local files.
 * 
 * @author André Stannek
 * @author Oliver Bestmann
 * @version 2009-09-05
 */
public final class DownloadManager
{

    /**
     * Downloads a track to the default download folder creating a folder for
     * artist and album. An existing file will not be overwritten.
     * 
     * @param track
     *            the track to download
     * @throws IOException
     *             on local file IO Error
     */
    public static void download(final Track track) throws IOException
    {
	download(track, new File(AbstractPreferences.instance()
		.getDownloadPath() + "/"
		+ track.getArtist() + "/" + track.getAlbum() + "/"));
    }

    /**
     * Downloads all tracks of an album to the default download folder creating
     * a folder for artist and album. Existing files will not be overwritten.
     * 
     * @param album
     *            the album to download
     * @throws IOException
     *             on local file IO Error
     */
    public static void download(final Album album) throws IOException
    {
	for (Track track : album.getTracks())
	{
	    download(track);
	}
    }

    /**
     * Downloads all tracks of an artist to the default download folder creating
     * a folder for artist and album. Existing files will not be overwritten.
     * 
     * @param artist
     *            the artist whos tracks should be downloaded
     * @throws IOException
     *             on server communication error or local file IO Error
     * @throws JSONException
     *             if preamp server provides invalid data
     */
    public static void download(final Artist artist) throws IOException,
	    JSONException
    {
	for (Album album : artist.getAlbums())
	{
	    download(album);
	}
    }

    /**
     * Downloads a track to a local file named after the
     * {@link de.preamp.clients.java.data.Track#toString() track} and ending
     * .mp3. Existing files will not be overwritten.
     * 
     * @param track
     *            the track to download
     * @param path
     *            the local folder where the track will be saved
     * @throws IOException
     *             on local file IO Error
     */
    public static void download(final Track track, final File path)
	    throws IOException
    {
	if (!path.exists() && !path.mkdirs())
	{
	    throw new IOException("folders could not be created");
	}
	final BufferedInputStream fileIS =
		new BufferedInputStream(new ProgressMonitorInputStream(null,
		"downloading...", track.getURL().openConnection()
		.getInputStream()));

	final BufferedOutputStream fileOS =
		new BufferedOutputStream(new FileOutputStream(path + "/"
		+ track.toString() + ".mp3"));

	final byte[] buf = new byte[1024 * 16];
	int length = fileIS.read(buf);
	while (length > 0)
	{
	    fileOS.write(buf, 0, length);
	    length = fileIS.read(buf);
	}

	fileOS.flush();
	fileOS.close();
	fileIS.close();
    }

    /**
     * Downloads all tracks of an album into a specified folder.
     * 
     * @param album
     *            the path where to download the album to
     * @param path
     *            the local path where the album is downloaded to
     * @throws IOException
     *             on server communication or local file error
     */
    public static void download(final Album album, final File path)
	    throws IOException
    {
	for (Track track : album.getTracks())
	{
	    download(track, path);
	}

    }

    /**
     * Downloads all tracks of an artist into a specified folder. In that folder
     * folders named after the albums will be created.
     * 
     * @param artist
     *            the artist who's tracks should be downloaded
     * @param path
     *            the local path where to download to
     * @throws IOException
     *             on server communication or local file error
     * @throws JSONException
     *             if server returns an invalid result
     */
    public static void download(final Artist artist, final File path)
	    throws IOException, JSONException
    {
	String albumName;
	File file;
	for (Album album : artist.getAlbums())
	{
	    albumName = album.toString();
	    for (Track track : album.getTracks())
	    {
		file = new File(path.toString() + albumName + "/");
		download(track, file);
	    }
	}
    }

    /**
     * masking utility class constructor.
     */
    private DownloadManager()
    {
	super();
    }

}
